/*
 * OREKIT-X
 * Copyright 2002-2008 CS Communication & Systemes
 * 
 * Parts of this software package have been licensed to CS
 * Communication & Systemes (CS) under one or more contributor license
 * agreements.  See the NOTICE file distributed with this work for
 * additional information.
 *  
 * This is an experimental copy of OREKIT from www.orekit.org.
 * Please use the original OREKIT from orekit.org for normal work
 * unrelated to this research project.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You
 * may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied.  See the License for the specific language governing
 * permissions and limitations under the License.
 */
package ore.frames;

import ore.Frame;
import ore.Transform;
import ore.errors.OrekitException;
import ore.time.AbsoluteDate;

import org.apache.commons.math.geometry.Rotation;
import org.apache.commons.math.geometry.Vector3D;


/**
 * International Terrestrial Reference Frame 2005.
 * 
 * Handles pole motion effects and depends on {@link TIRF2000Frame},
 * its parent frame.
 * 
 * @author Luc Maisonobe
 */
class ITRF2005Frame
    extends Frame
{
    /**
     * S' rate in radians per julian century.  Approximately -47
     * microarcsecond per julian century (Lambert and Bizouard, 2002)
     */
    private static final double S_PRIME_RATE = -47e-6 * RADIANS_PER_ARC_SECOND;


    /** 
     * Cached date to avoid useless computation.
     */
    private AbsoluteDate cachedDate;


    /** 
     * Ignoring tidal effects.
     * 
     * @param date the current date
     * @param name the string representation
     * 
     * @exception OrekitException if nutation cannot be computed
     */
    protected ITRF2005Frame(AbsoluteDate date, String name)
        throws OrekitException
    {
        this(true, date, name);
    }
    /** 
     * @param ignoreTidalEffects if true, tidal effects are ignored
     * @param date the current date
     * @param name the string representation
     * 
     * @exception OrekitException if nutation cannot be computed
     */
    protected ITRF2005Frame(boolean ignoreTidalEffects, AbsoluteDate date, String name)
        throws OrekitException
    {
        super(FramesFactory.getTIRF2000(ignoreTidalEffects), null, name);
        /*
         * Everything is in place, we can now synchronize the frame
         */
        this.updateFrame(date);

    }


    /** 
     * Update the frame to the given date.  The update considers the
     * pole motion from IERS data.
     * 
     * @param date new value of the date
     * 
     * @exception OrekitException if the nutation model data embedded
     * in the library cannot be read
     */
    protected void updateFrame(final AbsoluteDate date)
        throws OrekitException
    {
        if ((this.cachedDate == null) || !this.cachedDate.equals(date)) {
            Rotation combined;
            {
                /*
                 * Offset from J2000 epoch in julian centuries
                 */
                final double tts = date.durationFrom(AbsoluteDate.J2000_EPOCH);
                final double ttc =  tts * JULIAN_CENTURY_PER_SECOND;
                /*
                 * Pole correction parameters
                 */
                final PoleCorrection pCorr = ((TIRF2000Frame) getParent()).getPoleCorrection(date);
                final PoleCorrection nCorr = nutationCorrection(date);
                /*
                 * Elementary rotations due to pole motion in terrestrial frame
                 */
                final Rotation r1 = new Rotation(Vector3D.PLUS_I, -(pCorr.getYp() + nCorr.getYp()));
                final Rotation r2 = new Rotation(Vector3D.PLUS_J, -(pCorr.getXp() + nCorr.getXp()));
                final Rotation r3 = new Rotation(Vector3D.PLUS_K, S_PRIME_RATE * ttc);
                /*
                 * Complete pole motion in terrestrial frame
                 */
                final Rotation wRot = r3.applyTo(r2.applyTo(r1));
                /*
                 * Combined effects
                 */
                combined = wRot.revert();
            }
            /*
             * Set up the transform from parent TIRF
             */
            this.setTransform(new Transform(combined, Vector3D.ZERO));
            this.cachedDate = date;
        }
    }

    /** 
     * Compute nutation correction due to tidal gravity.
     * 
     * @param date current date
     * 
     * @return Nutation correction
     */
    private PoleCorrection nutationCorrection(final AbsoluteDate date) {
        /*
         * This factor seems to be of order of magnitude a few tens of
         * micro arcseconds. It is computed from the classical
         * approach (not the new one used here) and hence requires
         * computation of GST, IAU2000A nutation, equations of
         * equinox, ..., et al..
         * 
         * For now, this term is ignored
         */
        return PoleCorrection.NULL_CORRECTION;
    }

}
